package com.example.newdemo.view.image.svg;



import android.graphics.Matrix;
import android.util.Log;

import com.example.newdemo.view.image.svg.SVG.Box;
import com.example.newdemo.view.image.svg.SVG.CSSClipRect;
import com.example.newdemo.view.image.svg.SVG.Circle;
import com.example.newdemo.view.image.svg.SVG.ClipPath;
import com.example.newdemo.view.image.svg.SVG.Colour;
import com.example.newdemo.view.image.svg.SVG.CurrentColor;
import com.example.newdemo.view.image.svg.SVG.Defs;
import com.example.newdemo.view.image.svg.SVG.Ellipse;
import com.example.newdemo.view.image.svg.SVG.GradientElement;
import com.example.newdemo.view.image.svg.SVG.GradientSpread;
import com.example.newdemo.view.image.svg.SVG.Group;
import com.example.newdemo.view.image.svg.SVG.HasTransform;
import com.example.newdemo.view.image.svg.SVG.Image;
import com.example.newdemo.view.image.svg.SVG.Length;
import com.example.newdemo.view.image.svg.SVG.Line;
import com.example.newdemo.view.image.svg.SVG.Marker;
import com.example.newdemo.view.image.svg.SVG.Mask;
import com.example.newdemo.view.image.svg.SVG.PaintReference;
import com.example.newdemo.view.image.svg.SVG.Path;
import com.example.newdemo.view.image.svg.SVG.PathDefinition;
import com.example.newdemo.view.image.svg.SVG.Pattern;
import com.example.newdemo.view.image.svg.SVG.PolyLine;
import com.example.newdemo.view.image.svg.SVG.Polygon;
import com.example.newdemo.view.image.svg.SVG.Rect;
import com.example.newdemo.view.image.svg.SVG.SolidColor;
import com.example.newdemo.view.image.svg.SVG.Stop;
import com.example.newdemo.view.image.svg.SVG.Style;
import com.example.newdemo.view.image.svg.SVG.Style.FillRule;
import com.example.newdemo.view.image.svg.SVG.Style.FontStyle;
import com.example.newdemo.view.image.svg.SVG.Style.LineCaps;
import com.example.newdemo.view.image.svg.SVG.Style.LineJoin;
import com.example.newdemo.view.image.svg.SVG.Style.TextAnchor;
import com.example.newdemo.view.image.svg.SVG.Style.TextDecoration;
import com.example.newdemo.view.image.svg.SVG.Style.TextDirection;
import com.example.newdemo.view.image.svg.SVG.Style.VectorEffect;
import com.example.newdemo.view.image.svg.SVG.Svg;
import com.example.newdemo.view.image.svg.SVG.SvgConditional;
import com.example.newdemo.view.image.svg.SVG.SvgConditionalContainer;
import com.example.newdemo.view.image.svg.SVG.SvgContainer;
import com.example.newdemo.view.image.svg.SVG.SvgElementBase;
import com.example.newdemo.view.image.svg.SVG.SvgLinearGradient;
import com.example.newdemo.view.image.svg.SVG.SvgObject;
import com.example.newdemo.view.image.svg.SVG.SvgPaint;
import com.example.newdemo.view.image.svg.SVG.SvgPreserveAspectRatioContainer;
import com.example.newdemo.view.image.svg.SVG.SvgRadialGradient;
import com.example.newdemo.view.image.svg.SVG.SvgViewBoxContainer;
import com.example.newdemo.view.image.svg.SVG.Switch;
import com.example.newdemo.view.image.svg.SVG.Symbol;
import com.example.newdemo.view.image.svg.SVG.TRef;
import com.example.newdemo.view.image.svg.SVG.TSpan;
import com.example.newdemo.view.image.svg.SVG.Text;
import com.example.newdemo.view.image.svg.SVG.TextChild;
import com.example.newdemo.view.image.svg.SVG.TextContainer;
import com.example.newdemo.view.image.svg.SVG.TextPath;
import com.example.newdemo.view.image.svg.SVG.TextPositionedContainer;
import com.example.newdemo.view.image.svg.SVG.TextRoot;
import com.example.newdemo.view.image.svg.SVG.TextSequence;
import com.example.newdemo.view.image.svg.SVG.Unit;
import com.example.newdemo.view.image.svg.SVG.Use;
import com.example.newdemo.view.image.svg.SVG.View;
import com.example.newdemo.view.image.svg.PreserveAspectRatio.Alignment;
import com.example.newdemo.view.image.svg.PreserveAspectRatio.Scale;
import com.example.newdemo.view.image.svg.CSSParser.MediaType;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DefaultHandler2;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.zip.GZIPInputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class SVGParser extends DefaultHandler2 {

    private static final String TAG = "SVGParser";
    private static final String SVG_NAMESPACE = "http://www.w3.org/2000/svg";
    private static final String XLINK_NAMESPACE = "http://www.w3.org/1999/xlink";
    private static final String FEATURE_STRING_PREFIX = "http://www.w3.org/TR/SVG11/feature#";
    private SVG svgDocument = null;
    private SvgContainer currentElement = null;

    private boolean ignoring = false;
    private int ignoreDepth;
    private boolean inMetadataElement = false;
    private String metadataTag = null;
    private StringBuilder metadataElementContents = null;
    private boolean inStyleElement = false;
    private StringBuilder styleElementContents = null;
    private HashSet<String> supportedFormats = null;
    private static final String TAG_SVG = "svg";
    private static final String TAG_A = "a";
    private static final String TAG_CIRCLE = "circle";
    private static final String TAG_CLIPPATH = "clipPath";
    private static final String TAG_DEFS = "defs";
    private static final String TAG_DESC = "desc";
    private static final String TAG_ELLIPSE = "ellipse";
    private static final String TAG_G = "g";
    private static final String TAG_IMAGE = "image";
    private static final String TAG_LINE = "line";
    private static final String TAG_LINEARGRADIENT = "linearGradient";
    private static final String TAG_MARKER = "marker";
    private static final String TAG_MASK = "mask";
    private static final String TAG_PATH = "path";
    private static final String TAG_PATTERN = "pattern";
    private static final String TAG_POLYGON = "polygon";
    private static final String TAG_POLYLINE = "polyline";
    private static final String TAG_RADIALGRADIENT = "radialGradient";
    private static final String TAG_RECT = "rect";
    private static final String TAG_SOLIDCOLOR = "solidColor";
    private static final String TAG_STOP = "stop";
    private static final String TAG_STYLE = "style";
    private static final String TAG_SWITCH = "switch";
    private static final String TAG_SYMBOL = "symbol";
    private static final String TAG_TEXT = "text";
    private static final String TAG_TEXTPATH = "textPath";
    private static final String TAG_TITLE = "title";
    private static final String TAG_TREF = "tref";
    private static final String TAG_TSPAN = "tspan";
    private static final String TAG_USE = "use";
    private static final String TAG_VIEW = "view";
    private static final String NONE = "none";
    private static final String CURRENTCOLOR = "currentColor";

    private static final String VALID_DISPLAY_VALUES = "|inline|block|list-item|run-in|compact|marker|table" +
                                            "|inline-table|table-row-group|table-header-group|table-footer-group" +
                                            "|table-row|table-column-group|table-column" +
                                            "|table-cell|table-caption|none|";

    private static final String VALID_VISIBILITY_VALUES = "|visible|hidden|collapse|";

    private static HashMap<String, Integer> colourKeywords = new HashMap();

    private static HashMap<String, Length> fontSizeKeywords = new HashMap(9);
    private static HashMap<String, Integer> fontWeightKeywords = new HashMap(13);
    private static HashMap<String, FontStyle> fontStyleKeywords = new HashMap(3);
    private static HashMap<String, Alignment> aspectRatioKeywords = new HashMap();
    protected static HashSet<String> supportedFeatures = new HashSet();

    static {
        colourKeywords.put("aliceblue", 15792383);
        colourKeywords.put("antiquewhite", 16444375);
        colourKeywords.put("aqua", 65535);
        colourKeywords.put("aquamarine", 8388564);
        colourKeywords.put("azure", 15794175);
        colourKeywords.put("beige", 16119260);
        colourKeywords.put("bisque", 16770244);
        colourKeywords.put("black", 0);
        colourKeywords.put("blanchedalmond", 16772045);
        colourKeywords.put("blue", 255);
        colourKeywords.put("blueviolet", 9055202);
        colourKeywords.put("brown", 10824234);
        colourKeywords.put("burlywood", 14596231);
        colourKeywords.put("cadetblue", 6266528);
        colourKeywords.put("chartreuse", 8388352);
        colourKeywords.put("chocolate", 13789470);
        colourKeywords.put("coral", 16744272);
        colourKeywords.put("cornflowerblue", 6591981);
        colourKeywords.put("cornsilk", 16775388);
        colourKeywords.put("crimson", 14423100);
        colourKeywords.put("cyan", 65535);
        colourKeywords.put("darkblue", 139);
        colourKeywords.put("darkcyan", 35723);
        colourKeywords.put("darkgoldenrod", 12092939);
        colourKeywords.put("darkgray", 11119017);
        colourKeywords.put("darkgreen", 25600);
        colourKeywords.put("darkgrey", 11119017);
        colourKeywords.put("darkkhaki", 12433259);
        colourKeywords.put("darkmagenta", 9109643);
        colourKeywords.put("darkolivegreen", 5597999);
        colourKeywords.put("darkorange", 16747520);
        colourKeywords.put("darkorchid", 10040012);
        colourKeywords.put("darkred", 9109504);
        colourKeywords.put("darksalmon", 15308410);
        colourKeywords.put("darkseagreen", 9419919);
        colourKeywords.put("darkslateblue", 4734347);
        colourKeywords.put("darkslategray", 3100495);
        colourKeywords.put("darkslategrey", 3100495);
        colourKeywords.put("darkturquoise", 52945);
        colourKeywords.put("darkviolet", 9699539);
        colourKeywords.put("deeppink", 16716947);
        colourKeywords.put("deepskyblue", 49151);
        colourKeywords.put("dimgray", 6908265);
        colourKeywords.put("dimgrey", 6908265);
        colourKeywords.put("dodgerblue", 2003199);
        colourKeywords.put("firebrick", 11674146);
        colourKeywords.put("floralwhite", 16775920);
        colourKeywords.put("forestgreen", 2263842);
        colourKeywords.put("fuchsia", 16711935);
        colourKeywords.put("gainsboro", 14474460);
        colourKeywords.put("ghostwhite", 16316671);
        colourKeywords.put("gold", 16766720);
        colourKeywords.put("goldenrod", 14329120);
        colourKeywords.put("gray", 8421504);
        colourKeywords.put("green", 32768);
        colourKeywords.put("greenyellow", 11403055);
        colourKeywords.put("grey", 8421504);
        colourKeywords.put("honeydew", 15794160);
        colourKeywords.put("hotpink", 16738740);
        colourKeywords.put("indianred", 13458524);
        colourKeywords.put("indigo", 4915330);
        colourKeywords.put("ivory", 16777200);
        colourKeywords.put("khaki", 15787660);
        colourKeywords.put("lavender", 15132410);
        colourKeywords.put("lavenderblush", 16773365);
        colourKeywords.put("lawngreen", 8190976);
        colourKeywords.put("lemonchiffon", 16775885);
        colourKeywords.put("lightblue", 11393254);
        colourKeywords.put("lightcoral", 15761536);
        colourKeywords.put("lightcyan", 14745599);
        colourKeywords.put("lightgoldenrodyellow", 16448210);
        colourKeywords.put("lightgray", 13882323);
        colourKeywords.put("lightgreen", 9498256);
        colourKeywords.put("lightgrey", 13882323);
        colourKeywords.put("lightpink", 16758465);
        colourKeywords.put("lightsalmon", 16752762);
        colourKeywords.put("lightseagreen", 2142890);
        colourKeywords.put("lightskyblue", 8900346);
        colourKeywords.put("lightslategray", 7833753);
        colourKeywords.put("lightslategrey", 7833753);
        colourKeywords.put("lightsteelblue", 11584734);
        colourKeywords.put("lightyellow", 16777184);
        colourKeywords.put("lime", 65280);
        colourKeywords.put("limegreen", 3329330);
        colourKeywords.put("linen", 16445670);
        colourKeywords.put("magenta", 16711935);
        colourKeywords.put("maroon", 8388608);
        colourKeywords.put("mediumaquamarine", 6737322);
        colourKeywords.put("mediumblue", 205);
        colourKeywords.put("mediumorchid", 12211667);
        colourKeywords.put("mediumpurple", 9662683);
        colourKeywords.put("mediumseagreen", 3978097);
        colourKeywords.put("mediumslateblue", 8087790);
        colourKeywords.put("mediumspringgreen", 64154);
        colourKeywords.put("mediumturquoise", 4772300);
        colourKeywords.put("mediumvioletred", 13047173);
        colourKeywords.put("midnightblue", 1644912);
        colourKeywords.put("mintcream", 16121850);
        colourKeywords.put("mistyrose", 16770273);
        colourKeywords.put("moccasin", 16770229);
        colourKeywords.put("navajowhite", 16768685);
        colourKeywords.put("navy", 128);
        colourKeywords.put("oldlace", 16643558);
        colourKeywords.put("olive", 8421376);
        colourKeywords.put("olivedrab", 7048739);
        colourKeywords.put("orange", 16753920);
        colourKeywords.put("orangered", 16729344);
        colourKeywords.put("orchid", 14315734);
        colourKeywords.put("palegoldenrod", 15657130);
        colourKeywords.put("palegreen", 10025880);
        colourKeywords.put("paleturquoise", 11529966);
        colourKeywords.put("palevioletred", 14381203);
        colourKeywords.put("papayawhip", 16773077);
        colourKeywords.put("peachpuff", 16767673);
        colourKeywords.put("peru", 13468991);
        colourKeywords.put("pink", 16761035);
        colourKeywords.put("plum", 14524637);
        colourKeywords.put("powderblue", 11591910);
        colourKeywords.put("purple", 8388736);
        colourKeywords.put("red", 16711680);
        colourKeywords.put("rosybrown", 12357519);
        colourKeywords.put("royalblue", 4286945);
        colourKeywords.put("saddlebrown", 9127187);
        colourKeywords.put("salmon", 16416882);
        colourKeywords.put("sandybrown", 16032864);
        colourKeywords.put("seagreen", 3050327);
        colourKeywords.put("seashell", 16774638);
        colourKeywords.put("sienna", 10506797);
        colourKeywords.put("silver", 12632256);
        colourKeywords.put("skyblue", 8900331);
        colourKeywords.put("slateblue", 6970061);
        colourKeywords.put("slategray", 7372944);
        colourKeywords.put("slategrey", 7372944);
        colourKeywords.put("snow", 16775930);
        colourKeywords.put("springgreen", 65407);
        colourKeywords.put("steelblue", 4620980);
        colourKeywords.put("tan", 13808780);
        colourKeywords.put("teal", 32896);
        colourKeywords.put("thistle", 14204888);
        colourKeywords.put("tomato", 16737095);
        colourKeywords.put("turquoise", 4251856);
        colourKeywords.put("violet", 15631086);
        colourKeywords.put("wheat", 16113331);
        colourKeywords.put("white", 16777215);
        colourKeywords.put("whitesmoke", 16119285);
        colourKeywords.put("yellow", 16776960);
        colourKeywords.put("yellowgreen", 10145074);
        fontSizeKeywords.put("xx-small", new SVG.Length(0.694F, Unit.pt));
        fontSizeKeywords.put("x-small", new Length(0.833F, Unit.pt));
        fontSizeKeywords.put("small", new Length(10.0F, Unit.pt));
        fontSizeKeywords.put("medium", new Length(12.0F, Unit.pt));
        fontSizeKeywords.put("large", new Length(14.4F, Unit.pt));
        fontSizeKeywords.put("x-large", new Length(17.3F, Unit.pt));
        fontSizeKeywords.put("xx-large", new Length(20.7F, Unit.pt));
        fontSizeKeywords.put("smaller", new Length(83.33F, Unit.percent));
        fontSizeKeywords.put("larger", new Length(120.0F, Unit.percent));
        fontWeightKeywords.put("normal", 400);
        fontWeightKeywords.put("bold", 700);
        fontWeightKeywords.put("bolder", 1);
        fontWeightKeywords.put("lighter", -1);
        fontWeightKeywords.put("100", 100);
        fontWeightKeywords.put("200", 200);
        fontWeightKeywords.put("300", 300);
        fontWeightKeywords.put("400", 400);
        fontWeightKeywords.put("500", 500);
        fontWeightKeywords.put("600", 600);
        fontWeightKeywords.put("700", 700);
        fontWeightKeywords.put("800", 800);
        fontWeightKeywords.put("900", 900);
        fontStyleKeywords.put("normal", FontStyle.Normal);
        fontStyleKeywords.put("italic", FontStyle.Italic);
        fontStyleKeywords.put("oblique", FontStyle.Oblique);
        aspectRatioKeywords.put("none", PreserveAspectRatio.Alignment.None);
        aspectRatioKeywords.put("xMinYMin", Alignment.XMinYMin);
        aspectRatioKeywords.put("xMidYMin", Alignment.XMidYMin);
        aspectRatioKeywords.put("xMaxYMin", Alignment.XMaxYMin);
        aspectRatioKeywords.put("xMinYMid", Alignment.XMinYMid);
        aspectRatioKeywords.put("xMidYMid", Alignment.XMidYMid);
        aspectRatioKeywords.put("xMaxYMid", Alignment.XMaxYMid);
        aspectRatioKeywords.put("xMinYMax", Alignment.XMinYMax);
        aspectRatioKeywords.put("xMidYMax", Alignment.XMidYMax);
        aspectRatioKeywords.put("xMaxYMax", Alignment.XMaxYMax);
        supportedFeatures.add("Structure");
        supportedFeatures.add("BasicStructure");
        supportedFeatures.add("ConditionalProcessing");
        supportedFeatures.add("Image");
        supportedFeatures.add("Style");
        supportedFeatures.add("ViewportAttribute");
        supportedFeatures.add("Shape");
        supportedFeatures.add("BasicText");
        supportedFeatures.add("PaintAttribute");
        supportedFeatures.add("BasicPaintAttribute");
        supportedFeatures.add("OpacityAttribute");
        supportedFeatures.add("BasicGraphicsAttribute");
        supportedFeatures.add("Marker");
        supportedFeatures.add("Gradient");
        supportedFeatures.add("Pattern");
        supportedFeatures.add("Clip");
        supportedFeatures.add("BasicClip");
        supportedFeatures.add("Mask");
        supportedFeatures.add("View");
    }

    public SVGParser() {
    }

    protected void setSupportedFormats(String[] mimeTypes) {
        this.supportedFormats = new HashSet(mimeTypes.length);
        Collections.addAll(this.supportedFormats, mimeTypes);
    }

    protected SVG parse(InputStream is) throws SVGParseException {
        if (!((InputStream)is).markSupported()) {
            is = new BufferedInputStream((InputStream)is);
        }

        try {
            ((InputStream)is).mark(3);

            int firstTwoBytes = ((InputStream)is).read() + (((InputStream)is).read() << 8);

            ((InputStream)is).reset();

            if (firstTwoBytes == 35615) {
                is = new GZIPInputStream((InputStream)is);
            }

        } catch (IOException var19) {
        }

        SAXParserFactory spf = SAXParserFactory.newInstance(); //xml解析器

        try {
            SAXParser sp = spf.newSAXParser();
            XMLReader xr = sp.getXMLReader();
            xr.setContentHandler(this);
            xr.setProperty("http://xml.org/sax/properties/lexical-handler", this);
            xr.parse(new InputSource((InputStream)is));
        } catch (IOException var15) {
            throw new SVGParseException("File error", var15);
        } catch (ParserConfigurationException var16) {
            throw new SVGParseException("XML Parser problem", var16);
        } catch (SAXException var17) {
            throw new SVGParseException("SVG parse error: " + var17.getMessage(), var17);
        } finally {
            try {
                ((InputStream)is).close();
            } catch (IOException var14) {
                Log.e("SVGParser", "Exception thrown closing input stream");
            }

        }

        return this.svgDocument;
    }

    public void startDocument() throws SAXException {
        super.startDocument();
        this.svgDocument = new SVG();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        if (this.ignoring) {
            ++this.ignoreDepth;
        } else if ("http://www.w3.org/2000/svg".equals(uri) || "".equals(uri)) {
            if (localName.equals("svg")) {
                this.svg(attributes);
            } else if (localName.equals("g")) {
                this.g(attributes);
            } else if (localName.equals("defs")) {
                this.defs(attributes);
            } else if (localName.equals("use")) {
                this.use(attributes);
            } else if (localName.equals("path")) {
                this.path(attributes);
            } else if (localName.equals("rect")) {
                this.rect(attributes);
            } else if (localName.equals("circle")) {
                this.circle(attributes);
            } else if (localName.equals("ellipse")) {
                this.ellipse(attributes);
            } else if (localName.equals("line")) {
                this.line(attributes);
            } else if (localName.equals("polyline")) {
                this.polyline(attributes);
            } else if (localName.equals("polygon")) {
                this.polygon(attributes);
            } else if (localName.equals("text")) {
                this.text(attributes);
            } else if (localName.equals("tspan")) {
                this.tspan(attributes);
            } else if (localName.equals("tref")) {
                this.tref(attributes);
            } else if (localName.equals("switch")) {
                this.zwitch(attributes);
            } else if (localName.equals("symbol")) {
                this.symbol(attributes);
            } else if (localName.equals("marker")) {
                this.marker(attributes);
            } else if (localName.equals("linearGradient")) {
                this.linearGradient(attributes);
            } else if (localName.equals("radialGradient")) {
                this.radialGradient(attributes);
            } else if (localName.equals("stop")) {
                this.stop(attributes);
            } else if (localName.equals("a")) {
                this.g(attributes);
            } else if (!localName.equals("title") && !localName.equals("desc")) {
                if (localName.equals("clipPath")) {
                    this.clipPath(attributes);
                } else if (localName.equals("textPath")) {
                    this.textPath(attributes);
                } else if (localName.equals("pattern")) {
                    this.pattern(attributes);
                } else if (localName.equals("image")) {
                    this.image(attributes);
                } else if (localName.equals("view")) {
                    this.view(attributes);
                } else if (localName.equals("mask")) {
                    this.mask(attributes);
                } else if (localName.equals("style")) {
                    this.style(attributes);
                } else if (localName.equals("solidColor")) {
                    this.solidColor(attributes);
                } else {
                    this.ignoring = true;
                    this.ignoreDepth = 1;
                }
            } else {
                this.inMetadataElement = true;
                this.metadataTag = localName;
            }

        }
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        if (!this.ignoring) {
            if (this.inMetadataElement) {
                if (this.metadataElementContents == null) {
                    this.metadataElementContents = new StringBuilder(length);
                }

                this.metadataElementContents.append(ch, start, length);
            } else if (this.inStyleElement) {
                if (this.styleElementContents == null) {
                    this.styleElementContents = new StringBuilder(length);
                }

                this.styleElementContents.append(ch, start, length);
            } else {
                if (this.currentElement instanceof TextContainer) {
                    SvgConditionalContainer parent = (SvgConditionalContainer)this.currentElement;
                    int numOlderSiblings = parent.children.size();
                    SvgObject previousSibling = numOlderSiblings == 0 ? null : (SvgObject)parent.children.get(numOlderSiblings - 1);
                    if (previousSibling instanceof TextSequence) {
                        ((TextSequence)previousSibling).text = ((TextSequence)previousSibling).text + new String(ch, start, length);
                    } else {
                        ((SvgConditionalContainer)this.currentElement).addChild(new TextSequence(new String(ch, start, length)));
                    }
                }

            }
        }
    }

    public void comment(char[] ch, int start, int length) throws SAXException {
        if (!this.ignoring) {
            if (this.inStyleElement) {
                if (this.styleElementContents == null) {
                    this.styleElementContents = new StringBuilder(length);
                }

                this.styleElementContents.append(ch, start, length);
            }
        }
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        if (this.ignoring && --this.ignoreDepth == 0) {
            this.ignoring = false;
        } else if ("http://www.w3.org/2000/svg".equals(uri) || "".equals(uri)) {
            if (!localName.equals("title") && !localName.equals("desc")) {
                if (localName.equals("style") && this.styleElementContents != null) {
                    this.inStyleElement = false;
                    this.parseCSSStyleSheet(this.styleElementContents.toString());
                    this.styleElementContents.setLength(0);
                } else {
                    if (localName.equals("svg") || localName.equals("defs")
                                                || localName.equals("g")
                                                || localName.equals("use")
                                                || localName.equals("image")
                                                || localName.equals("text")
                                                || localName.equals("tspan")
                                                || localName.equals("switch")
                                                || localName.equals("symbol")
                                                || localName.equals("marker")
                                                || localName.equals("linearGradient")
                                                || localName.equals("radialGradient")
                                                || localName.equals("stop")
                                                || localName.equals("clipPath")
                                                || localName.equals("textPath")
                                                || localName.equals("pattern")
                                                || localName.equals("view")
                                                || localName.equals("mask")
                                                || localName.equals("solidColor")) {

                        this.currentElement = ((SvgObject)this.currentElement).parent;
                    }

                }
            } else {
                this.inMetadataElement = false;
                if (this.metadataTag.equals("title")) {
                    this.svgDocument.setTitle(this.metadataElementContents.toString());
                } else if (this.metadataTag.equals("desc")) {
                    this.svgDocument.setDesc(this.metadataElementContents.toString());
                }

                this.metadataElementContents.setLength(0);
            }
        }
    }

    public void endDocument() throws SAXException {
        super.endDocument();
    }

    private void dumpNode(SvgObject elem, String indent) {
        Log.d("SVGParser", indent + elem);
        if (elem instanceof SVG.SvgConditionalContainer) {
            indent = indent + "  ";
            Iterator var4 = ((SVG.SvgConditionalContainer)elem).children.iterator();

            while(var4.hasNext()) {
                SvgObject child = (SvgObject)var4.next();
                this.dumpNode(child, indent);
            }
        }

    }

    private void debug(String format, Object... args) {
    }

    private void svg(Attributes attributes) throws SAXException {
        this.debug("<svg>");
        Svg obj = new Svg();
        obj.document = this.svgDocument;
        obj.parent = this.currentElement;
        this.parseAttributesCore(obj, attributes);
        this.parseAttributesStyle(obj, attributes);
        this.parseAttributesConditional(obj, attributes);
        this.parseAttributesViewBox(obj, attributes);
        this.parseAttributesSVG(obj, attributes);
        if (this.currentElement == null) {
            this.svgDocument.setRootElement(obj);
        } else {
            this.currentElement.addChild(obj);
        }

        this.currentElement = obj;
    }

    private void parseAttributesSVG(Svg obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();

            //SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 26:
                    obj.height = parseLength(val);
                    if (obj.height.isNegative()) {
                        throw new SAXException("Invalid <svg> element. height cannot be negative");
                    }
                    break;
                case 80:
                    obj.version = val;
                    break;
                case 82:
                    obj.width = parseLength(val);
                    if (obj.width.isNegative()) {
                        throw new SAXException("Invalid <svg> element. width cannot be negative");
                    }
                    break;
                case 83:
                    obj.x = parseLength(val);
                    break;
                case 84:
                    obj.y = parseLength(val);
            }
        }

    }

    private void g(Attributes attributes) throws SAXException {
        this.debug("<g>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Group obj = new Group();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void defs(Attributes attributes) throws SAXException {
        this.debug("<defs>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Defs obj = new Defs();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void use(Attributes attributes) throws SAXException {
        this.debug("<use>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Use obj = new Use();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesUse(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesUse(Use obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //$SWITCH_TABLE$com$caverock$androidsvg$SVGParser$SVGAttr()[]
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 26:
                    obj.height = parseLength(val);
                    if (obj.height.isNegative()) {
                        throw new SAXException("Invalid <use> element. height cannot be negative");
                    }
                    break;
                case 27:
                    if ("http://www.w3.org/1999/xlink".equals(attributes.getURI(i))) {
                        obj.href = val;
                    }
                    break;
                case 82:
                    obj.width = parseLength(val);
                    if (obj.width.isNegative()) {
                        throw new SAXException("Invalid <use> element. width cannot be negative");
                    }
                    break;
                case 83:
                    obj.x = parseLength(val);
                    break;
                case 84:
                    obj.y = parseLength(val);
            }
        }

    }

    private void image(Attributes attributes) throws SAXException {
        this.debug("<image>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Image obj = new Image();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesImage(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesImage(Image obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //$SWITCH_TABLE$com$caverock$androidsvg$SVGParser$SVGAttr()[SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()]
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 26:
                    obj.height = parseLength(val);
                    if (obj.height.isNegative()) {
                        throw new SAXException("Invalid <use> element. height cannot be negative");
                    }
                    break;
                case 27:
                    if ("http://www.w3.org/1999/xlink".equals(attributes.getURI(i))) {
                        obj.href = val;
                    }
                    break;
                case 49:
                    parsePreserveAspectRatio(obj, val);
                    break;
                case 82:
                    obj.width = parseLength(val);
                    if (obj.width.isNegative()) {
                        throw new SAXException("Invalid <use> element. width cannot be negative");
                    }
                    break;
                case 83:
                    obj.x = parseLength(val);
                    break;
                case 84:
                    obj.y = parseLength(val);
            }
        }

    }

    private void path(Attributes attributes) throws SAXException {
        this.debug("<path>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Path obj = new Path();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesPath(obj, attributes);
            this.currentElement.addChild(obj);
        }
    }

    private void parseAttributesPath(Path obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //$SWITCH_TABLE$com$caverock$androidsvg$SVGParser$SVGAttr()[SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()]
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 14:
                    obj.d = parsePath(val);
                    break;
                case 44:
                    obj.pathLength = parseFloat(val);
                    if (obj.pathLength < 0.0F) {
                        throw new SAXException("Invalid <path> element. pathLength cannot be negative");
                    }
            }
        }

    }

    private void rect(Attributes attributes) throws SAXException {
        this.debug("<rect>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Rect obj = new Rect();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesRect(obj, attributes);
            this.currentElement.addChild(obj);
        }
    }

    private void parseAttributesRect(Rect obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //$SWITCH_TABLE$com$caverock$androidsvg$SVGParser$SVGAttr()[]
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 26:
                    obj.height = parseLength(val);
                    if (obj.height.isNegative()) {
                        throw new SAXException("Invalid <rect> element. height cannot be negative");
                    }
                    break;
                case 57:
                    obj.rx = parseLength(val);
                    if (obj.rx.isNegative()) {
                        throw new SAXException("Invalid <rect> element. rx cannot be negative");
                    }
                    break;
                case 58:
                    obj.ry = parseLength(val);
                    if (obj.ry.isNegative()) {
                        throw new SAXException("Invalid <rect> element. ry cannot be negative");
                    }
                    break;
                case 82:
                    obj.width = parseLength(val);
                    if (obj.width.isNegative()) {
                        throw new SAXException("Invalid <rect> element. width cannot be negative");
                    }
                    break;
                case 83:
                    obj.x = parseLength(val);
                    break;
                case 84:
                    obj.y = parseLength(val);
            }
        }

    }

    private void circle(Attributes attributes) throws SAXException {
        this.debug("<circle>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Circle obj = new Circle();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesCircle(obj, attributes);
            this.currentElement.addChild(obj);
        }
    }

    private void parseAttributesCircle(Circle obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //$SWITCH_TABLE$com$caverock$androidsvg$SVGParser$SVGAttr()[SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()]
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 7:
                    obj.cx = parseLength(val);
                    break;
                case 8:
                    obj.cy = parseLength(val);
                    break;
                case 50:
                    obj.r = parseLength(val);
                    if (obj.r.isNegative()) {
                        throw new SAXException("Invalid <circle> element. r cannot be negative");
                    }
            }
        }

    }

    private void ellipse(Attributes attributes) throws SAXException {
        this.debug("<ellipse>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Ellipse obj = new Ellipse();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesEllipse(obj, attributes);
            this.currentElement.addChild(obj);
        }
    }

    private void parseAttributesEllipse(Ellipse obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //$SWITCH_TABLE$com$caverock$androidsvg$SVGParser$SVGAttr()[SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()]
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 7:
                    obj.cx = parseLength(val);
                    break;
                case 8:
                    obj.cy = parseLength(val);
                    break;
                case 57:
                    obj.rx = parseLength(val);
                    if (obj.rx.isNegative()) {
                        throw new SAXException("Invalid <ellipse> element. rx cannot be negative");
                    }
                    break;
                case 58:
                    obj.ry = parseLength(val);
                    if (obj.ry.isNegative()) {
                        throw new SAXException("Invalid <ellipse> element. ry cannot be negative");
                    }
            }
        }

    }

    private void line(Attributes attributes) throws SAXException {
        this.debug("<line>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Line obj = new Line();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesLine(obj, attributes);
            this.currentElement.addChild(obj);
        }
    }

    private void parseAttributesLine(Line obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 85:
                    obj.x1 = parseLength(val);
                    break;
                case 86:
                    obj.y1 = parseLength(val);
                    break;
                case 87:
                    obj.x2 = parseLength(val);
                    break;
                case 88:
                    obj.y2 = parseLength(val);
            }
        }

    }

    private void polyline(Attributes attributes) throws SAXException {
        this.debug("<polyline>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            PolyLine obj = new PolyLine();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesPolyLine(obj, attributes, "polyline");
            this.currentElement.addChild(obj);
        }
    }

    private void parseAttributesPolyLine(PolyLine obj, Attributes attributes, String tag) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            if (SVGParser.SVGAttr.fromString(attributes.getLocalName(i)) == SVGParser.SVGAttr.points) {
                SVGParser.TextScanner scan = new SVGParser.TextScanner(attributes.getValue(i));
                List<Float> points = new ArrayList();
                scan.skipWhitespace();

                Float f;
                while(!scan.empty()) {
                    Float x = scan.nextFloat();
                    if (x == null) {
                        throw new SAXException("Invalid <" + tag + "> points attribute. Non-coordinate content found in list.");
                    }

                    scan.skipCommaWhitespace();
                    f = scan.nextFloat();
                    if (f == null) {
                        throw new SAXException("Invalid <" + tag + "> points attribute. There should be an even number of coordinates.");
                    }

                    scan.skipCommaWhitespace();
                    points.add(x);
                    points.add(f);
                }

                obj.points = new float[points.size()];
                int j = 0;

                for(Iterator var9 = points.iterator(); var9.hasNext(); obj.points[j++] = f) {
                    f = (Float)var9.next();
                }
            }
        }

    }

    private void polygon(Attributes attributes) throws SAXException {
        this.debug("<polygon>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Polygon obj = new Polygon();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesPolyLine(obj, attributes, "polygon");
            this.currentElement.addChild(obj);
        }
    }

    private void text(Attributes attributes) throws SAXException {
        this.debug("<text>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Text obj = new Text();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesTextPosition(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesTextPosition(TextPositionedContainer obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 10:
                    obj.dx = parseLengthList(val);
                    break;
                case 11:
                    obj.dy = parseLengthList(val);
                    break;
                case 83:
                    obj.x = parseLengthList(val);
                    break;
                case 84:
                    obj.y = parseLengthList(val);
            }
        }

    }

    private void tspan(Attributes attributes) throws SAXException {
        this.debug("<tspan>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else if (!(this.currentElement instanceof TextContainer)) {
            throw new SAXException("Invalid document. <tspan> elements are only valid inside <text> or other <tspan> elements.");
        } else {
            TSpan obj = new TSpan();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesTextPosition(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
            if (obj.parent instanceof TextRoot) {
                obj.setTextRoot((TextRoot)obj.parent);
            } else {
                obj.setTextRoot(((TextChild)obj.parent).getTextRoot());
            }

        }
    }

    private void tref(Attributes attributes) throws SAXException {
        this.debug("<tref>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else if (!(this.currentElement instanceof TextContainer)) {
            throw new SAXException("Invalid document. <tref> elements are only valid inside <text> or <tspan> elements.");
        } else {
            TRef obj = new TRef();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesTRef(obj, attributes);
            this.currentElement.addChild(obj);
            if (obj.parent instanceof TextRoot) {
                obj.setTextRoot((TextRoot)obj.parent);
            } else {
                obj.setTextRoot(((TextChild)obj.parent).getTextRoot());
            }

        }
    }

    private void parseAttributesTRef(TRef obj, Attributes attributes) throws SAXException {
        int i = 0;

        while(i < attributes.getLength()) {
            String val = attributes.getValue(i).trim();
            //SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 27:
                    if ("http://www.w3.org/1999/xlink".equals(attributes.getURI(i))) {
                        obj.href = val;
                    }
                default:
                    ++i;
            }
        }

    }

    private void zwitch(Attributes attributes) throws SAXException {
        this.debug("<switch>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Switch obj = new Switch();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesConditional(SvgConditional obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //$SWITCH_TABLE$com$caverock$androidsvg$SVGParser$SVGAttr()[SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()]
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 53:
                    obj.setRequiredFeatures(parseRequiredFeatures(val));
                    break;
                case 54:
                    obj.setRequiredExtensions(val);
                    break;
                case 55:
                    obj.setRequiredFormats(parseRequiredFormats(val));
                    break;
                case 56:
                    List<String> fonts = parseFontFamily(val);
                    Set<String> fontSet = fonts != null ? new HashSet(fonts) : new HashSet(0);
                    obj.setRequiredFonts(fontSet);
                    break;
                case 74:
                    obj.setSystemLanguage(parseSystemLanguage(val));
            }
        }

    }

    private void symbol(Attributes attributes) throws SAXException {
        this.debug("<symbol>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Symbol obj = new Symbol();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesViewBox(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void marker(Attributes attributes) throws SAXException {
        this.debug("<marker>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Marker obj = new Marker();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesViewBox(obj, attributes);
            this.parseAttributesMarker(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesMarker(Marker obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //$SWITCH_TABLE$com$caverock$androidsvg$SVGParser$SVGAttr()[SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()]
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 33:
                    obj.markerHeight = parseLength(val);
                    if (obj.markerHeight.isNegative()) {
                        throw new SAXException("Invalid <marker> element. markerHeight cannot be negative");
                    }
                    break;
                case 34:
                    if ("strokeWidth".equals(val)) {
                        obj.markerUnitsAreUser = false;
                    } else {
                        if (!"userSpaceOnUse".equals(val)) {
                            throw new SAXException("Invalid value for attribute markerUnits");
                        }

                        obj.markerUnitsAreUser = true;
                    }
                    break;
                case 35:
                    obj.markerWidth = parseLength(val);
                    if (obj.markerWidth.isNegative()) {
                        throw new SAXException("Invalid <marker> element. markerWidth cannot be negative");
                    }
                    break;
                case 42:
                    if ("auto".equals(val)) {
                        obj.orient = 0.0F / 0.0;
                    } else {
                        obj.orient = parseFloat(val);
                    }
                    break;
                case 51:
                    obj.refX = parseLength(val);
                    break;
                case 52:
                    obj.refY = parseLength(val);
            }
        }

    }

    private void linearGradient(Attributes attributes) throws SAXException {
        this.debug("<linearGradiant>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            SvgLinearGradient obj = new SvgLinearGradient();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesGradient(obj, attributes);
            this.parseAttributesLinearGradient(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesGradient(GradientElement obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 24:
                    obj.gradientTransform = this.parseTransformList(val);
                    break;
                case 25:
                    if ("objectBoundingBox".equals(val)) {
                        obj.gradientUnitsAreUser = false;
                    } else {
                        if (!"userSpaceOnUse".equals(val)) {
                            throw new SAXException("Invalid value for attribute gradientUnits");
                        }

                        obj.gradientUnitsAreUser = true;
                    }
                    break;
                case 27:
                    if ("http://www.w3.org/1999/xlink".equals(attributes.getURI(i))) {
                        obj.href = val;
                    }
                    break;
                case 61:
                    try {
                        obj.spreadMethod = GradientSpread.valueOf(val);
                    } catch (IllegalArgumentException var6) {
                        throw new SAXException("Invalid spreadMethod attribute. \"" + val + "\" is not a valid value.");
                    }
            }
        }

    }

    private void parseAttributesLinearGradient(SvgLinearGradient obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 85:
                    obj.x1 = parseLength(val);
                    break;
                case 86:
                    obj.y1 = parseLength(val);
                    break;
                case 87:
                    obj.x2 = parseLength(val);
                    break;
                case 88:
                    obj.y2 = parseLength(val);
            }
        }

    }

    private void radialGradient(Attributes attributes) throws SAXException {
        this.debug("<radialGradient>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            SvgRadialGradient obj = new SvgRadialGradient();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesGradient(obj, attributes);
            this.parseAttributesRadialGradient(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesRadialGradient(SvgRadialGradient obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            //SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 7:
                    obj.cx = parseLength(val);
                    break;
                case 8:
                    obj.cy = parseLength(val);
                    break;
                case 12:
                    obj.fx = parseLength(val);
                    break;
                case 13:
                    obj.fy = parseLength(val);
                    break;
                case 50:
                    obj.r = parseLength(val);
                    if (obj.r.isNegative()) {
                        throw new SAXException("Invalid <radialGradient> element. r cannot be negative");
                    }
            }
        }

    }

    private void stop(Attributes attributes) throws SAXException {
        this.debug("<stop>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else if (!(this.currentElement instanceof GradientElement)) {
            throw new SAXException("Invalid document. <stop> elements are only valid inside <linearGradiant> or <radialGradient> elements.");
        } else {
            Stop obj = new Stop();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesStop(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesStop(Stop obj, Attributes attributes) throws SAXException {
        int i = 0;

        while(i < attributes.getLength()) {
            String val = attributes.getValue(i).trim();
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 40:
                    obj.offset = this.parseGradiantOffset(val);
                default:
                    ++i;
            }
        }

    }

    private Float parseGradiantOffset(String val) throws SAXException {
        if (val.length() == 0) {
            throw new SAXException("Invalid offset value in <stop> (empty string)");
        } else {
            int end = val.length();
            boolean isPercent = false;
            if (val.charAt(val.length() - 1) == '%') {
                --end;
                isPercent = true;
            }

            try {
                float scalar = Float.parseFloat(val.substring(0, end));
                if (isPercent) {
                    scalar /= 100.0F;
                }

                return scalar < 0.0F ? 0.0F : (scalar > 100.0F ? 100.0F : scalar);
            } catch (NumberFormatException var5) {
                throw new SAXException("Invalid offset value in <stop>: " + val, var5);
            }
        }
    }

    private void solidColor(Attributes attributes) throws SAXException {
        this.debug("<solidColor>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            SolidColor obj = new SolidColor();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void clipPath(Attributes attributes) throws SAXException {
        this.debug("<clipPath>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            ClipPath obj = new ClipPath();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesTransform(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesClipPath(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesClipPath(ClipPath obj, Attributes attributes) throws SAXException {
        int i = 0;

        while(i < attributes.getLength()) {
            String val = attributes.getValue(i).trim();
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 4:
                    if ("objectBoundingBox".equals(val)) {
                        obj.clipPathUnitsAreUser = false;
                    } else {
                        if (!"userSpaceOnUse".equals(val)) {
                            throw new SAXException("Invalid value for attribute clipPathUnits");
                        }

                        obj.clipPathUnitsAreUser = true;
                    }
                default:
                    ++i;
            }
        }

    }

    private void textPath(Attributes attributes) throws SAXException {
        this.debug("<textPath>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            TextPath obj = new TextPath();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesTextPath(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
            if (obj.parent instanceof TextRoot) {
                obj.setTextRoot((TextRoot)obj.parent);
            } else {
                obj.setTextRoot(((TextChild)obj.parent).getTextRoot());
            }

        }
    }

    private void parseAttributesTextPath(TextPath obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 27:
                    if ("http://www.w3.org/1999/xlink".equals(attributes.getURI(i))) {
                        obj.href = val;
                    }
                    break;
                case 62:
                    obj.startOffset = parseLength(val);
            }
        }

    }

    private void pattern(Attributes attributes) throws SAXException {
        this.debug("<pattern>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Pattern obj = new Pattern();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesViewBox(obj, attributes);
            this.parseAttributesPattern(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesPattern(Pattern obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 26:
                    obj.height = parseLength(val);
                    if (obj.height.isNegative()) {
                        throw new SAXException("Invalid <pattern> element. height cannot be negative");
                    }
                    break;
                case 27:
                    if ("http://www.w3.org/1999/xlink".equals(attributes.getURI(i))) {
                        obj.href = val;
                    }
                    break;
                case 45:
                    if ("objectBoundingBox".equals(val)) {
                        obj.patternContentUnitsAreUser = false;
                    } else {
                        if (!"userSpaceOnUse".equals(val)) {
                            throw new SAXException("Invalid value for attribute patternContentUnits");
                        }

                        obj.patternContentUnitsAreUser = true;
                    }
                    break;
                case 46:
                    obj.patternTransform = this.parseTransformList(val);
                    break;
                case 47:
                    if ("objectBoundingBox".equals(val)) {
                        obj.patternUnitsAreUser = false;
                    } else {
                        if (!"userSpaceOnUse".equals(val)) {
                            throw new SAXException("Invalid value for attribute patternUnits");
                        }

                        obj.patternUnitsAreUser = true;
                    }
                    break;
                case 82:
                    obj.width = parseLength(val);
                    if (obj.width.isNegative()) {
                        throw new SAXException("Invalid <pattern> element. width cannot be negative");
                    }
                    break;
                case 83:
                    obj.x = parseLength(val);
                    break;
                case 84:
                    obj.y = parseLength(val);
            }
        }

    }

    private void view(Attributes attributes) throws SAXException {
        this.debug("<view>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            View obj = new View();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesViewBox(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void mask(Attributes attributes) throws SAXException {
        this.debug("<mask>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            Mask obj = new Mask();
            obj.document = this.svgDocument;
            obj.parent = this.currentElement;
            this.parseAttributesCore(obj, attributes);
            this.parseAttributesStyle(obj, attributes);
            this.parseAttributesConditional(obj, attributes);
            this.parseAttributesMask(obj, attributes);
            this.currentElement.addChild(obj);
            this.currentElement = obj;
        }
    }

    private void parseAttributesMask(Mask obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 26:
                    obj.height = parseLength(val);
                    if (obj.height.isNegative()) {
                        throw new SAXException("Invalid <mask> element. height cannot be negative");
                    }
                    break;
                case 37:
                    if ("objectBoundingBox".equals(val)) {
                        obj.maskContentUnitsAreUser = false;
                    } else {
                        if (!"userSpaceOnUse".equals(val)) {
                            throw new SAXException("Invalid value for attribute maskContentUnits");
                        }

                        obj.maskContentUnitsAreUser = true;
                    }
                    break;
                case 38:
                    if ("objectBoundingBox".equals(val)) {
                        obj.maskUnitsAreUser = false;
                    } else {
                        if (!"userSpaceOnUse".equals(val)) {
                            throw new SAXException("Invalid value for attribute maskUnits");
                        }

                        obj.maskUnitsAreUser = true;
                    }
                    break;
                case 82:
                    obj.width = parseLength(val);
                    if (obj.width.isNegative()) {
                        throw new SAXException("Invalid <mask> element. width cannot be negative");
                    }
                    break;
                case 83:
                    obj.x = parseLength(val);
                    break;
                case 84:
                    obj.y = parseLength(val);
            }
        }

    }

    private void parseAttributesCore(SvgElementBase obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String qname = attributes.getQName(i);
            if (qname.equals("id") || qname.equals("xml:id")) {
                obj.id = attributes.getValue(i).trim();
                break;
            }

            if (qname.equals("xml:space")) {
                String val = attributes.getValue(i).trim();
                if ("default".equals(val)) {
                    obj.spacePreserve = Boolean.FALSE;
                } else {
                    if (!"preserve".equals(val)) {
                        throw new SAXException("Invalid value for \"xml:space\" attribute: " + val);
                    }

                    obj.spacePreserve = Boolean.TRUE;
                }
                break;
            }
        }

    }

    private void parseAttributesStyle(SvgElementBase obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            if (val.length() != 0) {
                switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                    case 1:
                        obj.classNames = CSSParser.parseClassAttribute(val);
                        break;
                    case 73:
                        parseStyle(obj, val);
                        break;
                    default:
                        if (obj.baseStyle == null) {
                            obj.baseStyle = new Style();
                        }

                        processStyleProperty(obj.baseStyle, attributes.getLocalName(i), attributes.getValue(i).trim());
                }
            }
        }

    }

    private static void parseStyle(SvgElementBase obj, String style) throws SAXException {
        SVGParser.TextScanner scan = new SVGParser.TextScanner(style.replaceAll("/\\*.*?\\*/", ""));

        while(true) {
            String propertyName = scan.nextToken(':');
            scan.skipWhitespace();
            if (!scan.consume(':')) {
                break;
            }

            scan.skipWhitespace();
            String propertyValue = scan.nextToken(';');
            if (propertyValue == null) {
                break;
            }

            scan.skipWhitespace();
            if (scan.empty() || scan.consume(';')) {
                if (obj.style == null) {
                    obj.style = new Style();
                }

                processStyleProperty(obj.style, propertyName, propertyValue);
                scan.skipWhitespace();
            }
        }

    }

    protected static void processStyleProperty(Style style, String localName, String val) throws SAXException {
        if (val.length() != 0) {
            if (!val.equals("inherit")) {
                //$SWITCH_TABLE$com$caverock$androidsvg$SVGParser$SVGAttr()[SVGParser.SVGAttr.fromString(localName).ordinal()]
                switch(SVGParser.SVGAttr.fromString(localName).ordinal()) {
                    case 2:
                        style.clip = parseClip(val);
                        style.specifiedFlags |= 1048576L;
                        break;
                    case 3:
                        style.clipPath = parseFunctionalIRI(val, localName);
                        style.specifiedFlags |= 268435456L;
                    case 4:
                    case 7:
                    case 8:
                    case 10:
                    case 11:
                    case 12:
                    case 13:
                    case 14:
                    case 24:
                    case 25:
                    case 26:
                    case 27:
                    case 28:
                    case 33:
                    case 34:
                    case 35:
                    case 37:
                    case 38:
                    case 39:
                    case 40:
                    case 42:
                    case 44:
                    case 45:
                    case 46:
                    case 47:
                    case 48:
                    case 49:
                    case 50:
                    case 51:
                    case 52:
                    case 53:
                    case 54:
                    case 55:
                    case 56:
                    case 57:
                    case 58:
                    case 61:
                    case 62:
                    case 73:
                    case 74:
                    case 77:
                    case 78:
                    case 80:
                    case 81:
                    case 82:
                    case 83:
                    case 84:
                    case 85:
                    case 86:
                    case 87:
                    case 88:
                    default:
                        break;
                    case 5:
                        style.clipRule = parseFillRule(val);
                        style.specifiedFlags |= 536870912L;
                        break;
                    case 6:
                        style.color = parseColour(val);
                        style.specifiedFlags |= 4096L;
                        break;
                    case 9:
                        style.direction = parseTextDirection(val);
                        style.specifiedFlags |= 68719476736L;
                        break;
                    case 15:
                        if (val.indexOf(124) < 0 && ("|inline|block|list-item|run-in|compact|marker|table|inline-table|table-row-group" +
                                                        "|table-header-group|table-footer-group" +
                                                        "|table-row|table-column-group|table-column" +
                                                        "|table-cell|table-caption|none|").indexOf('|' + val + '|') != -1) {
                            style.display = !val.equals("none");
                            style.specifiedFlags |= 16777216L;
                            break;
                        }

                        throw new SAXException("Invalid value for \"display\" attribute: " + val);
                    case 16:
                        style.fill = parsePaintSpecifier(val, "fill");
                        style.specifiedFlags |= 1L;
                        break;
                    case 17:
                        style.fillRule = parseFillRule(val);
                        style.specifiedFlags |= 2L;
                        break;
                    case 18:
                        style.fillOpacity = parseOpacity(val);
                        style.specifiedFlags |= 4L;
                        break;
                    case 19:
                        parseFont(style, val);
                        break;
                    case 20:
                        style.fontFamily = parseFontFamily(val);
                        style.specifiedFlags |= 8192L;
                        break;
                    case 21:
                        style.fontSize = parseFontSize(val);
                        style.specifiedFlags |= 16384L;
                        break;
                    case 22:
                        style.fontWeight = parseFontWeight(val);
                        style.specifiedFlags |= 32768L;
                        break;
                    case 23:
                        style.fontStyle = parseFontStyle(val);
                        style.specifiedFlags |= 65536L;
                        break;
                    case 29:
                        style.markerStart = parseFunctionalIRI(val, localName);
                        style.markerMid = style.markerStart;
                        style.markerEnd = style.markerStart;
                        style.specifiedFlags |= 14680064L;
                        break;
                    case 30:
                        style.markerStart = parseFunctionalIRI(val, localName);
                        style.specifiedFlags |= 2097152L;
                        break;
                    case 31:
                        style.markerMid = parseFunctionalIRI(val, localName);
                        style.specifiedFlags |= 4194304L;
                        break;
                    case 32:
                        style.markerEnd = parseFunctionalIRI(val, localName);
                        style.specifiedFlags |= 8388608L;
                        break;
                    case 36:
                        style.mask = parseFunctionalIRI(val, localName);
                        style.specifiedFlags |= 1073741824L;
                        break;
                    case 41:
                        style.opacity = parseOpacity(val);
                        style.specifiedFlags |= 2048L;
                        break;
                    case 43:
                        style.overflow = parseOverflow(val);
                        style.specifiedFlags |= 524288L;
                        break;
                    case 59:
                        if (val.equals("currentColor")) {
                            style.solidColor = CurrentColor.getInstance();
                        } else {
                            style.solidColor = parseColour(val);
                        }

                        style.specifiedFlags |= 2147483648L;
                        break;
                    case 60:
                        style.solidOpacity = parseOpacity(val);
                        style.specifiedFlags |= 4294967296L;
                        break;
                    case 63:
                        if (val.equals("currentColor")) {
                            style.stopColor = CurrentColor.getInstance();
                        } else {
                            style.stopColor = parseColour(val);
                        }

                        style.specifiedFlags |= 67108864L;
                        break;
                    case 64:
                        style.stopOpacity = parseOpacity(val);
                        style.specifiedFlags |= 134217728L;
                        break;
                    case 65:
                        style.stroke = parsePaintSpecifier(val, "stroke");
                        style.specifiedFlags |= 8L;
                        break;
                    case 66:
                        if ("none".equals(val)) {
                            style.strokeDashArray = null;
                        } else {
                            style.strokeDashArray = parseStrokeDashArray(val);
                        }

                        style.specifiedFlags |= 512L;
                        break;
                    case 67:
                        style.strokeDashOffset = parseLength(val);
                        style.specifiedFlags |= 1024L;
                        break;
                    case 68:
                        style.strokeLineCap = parseStrokeLineCap(val);
                        style.specifiedFlags |= 64L;
                        break;
                    case 69:
                        style.strokeLineJoin = parseStrokeLineJoin(val);
                        style.specifiedFlags |= 128L;
                        break;
                    case 70:
                        style.strokeMiterLimit = parseFloat(val);
                        style.specifiedFlags |= 256L;
                        break;
                    case 71:
                        style.strokeOpacity = parseOpacity(val);
                        style.specifiedFlags |= 16L;
                        break;
                    case 72:
                        style.strokeWidth = parseLength(val);
                        style.specifiedFlags |= 32L;
                        break;
                    case 75:
                        style.textAnchor = parseTextAnchor(val);
                        style.specifiedFlags |= 262144L;
                        break;
                    case 76:
                        style.textDecoration = parseTextDecoration(val);
                        style.specifiedFlags |= 131072L;
                        break;
                    case 79:
                        style.vectorEffect = parseVectorEffect(val);
                        style.specifiedFlags |= 34359738368L;
                        break;
                    case 89:
                        if (val.equals("currentColor")) {
                            style.viewportFill = CurrentColor.getInstance();
                        } else {
                            style.viewportFill = parseColour(val);
                        }

                        style.specifiedFlags |= 8589934592L;
                        break;
                    case 90:
                        style.viewportFillOpacity = parseOpacity(val);
                        style.specifiedFlags |= 17179869184L;
                        break;
                    case 91:
                        if (val.indexOf(124) >= 0 || "|visible|hidden|collapse|".indexOf('|' + val + '|') == -1) {
                            throw new SAXException("Invalid value for \"visibility\" attribute: " + val);
                        }

                        style.visibility = val.equals("visible");
                        style.specifiedFlags |= 33554432L;
                }

            }
        }
    }

    private void parseAttributesViewBox(SvgViewBoxContainer obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            String val = attributes.getValue(i).trim();
            switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                case 49:
                    parsePreserveAspectRatio(obj, val);
                    break;
                case 81:
                    obj.viewBox = parseViewBox(val);
            }
        }

    }

    private void parseAttributesTransform(HasTransform obj, Attributes attributes) throws SAXException {
        for(int i = 0; i < attributes.getLength(); ++i) {
            if (SVGParser.SVGAttr.fromString(attributes.getLocalName(i)) == SVGParser.SVGAttr.transform) {
                obj.setTransform(this.parseTransformList(attributes.getValue(i)));
            }
        }

    }

    private Matrix parseTransformList(String val) throws SAXException {
        Matrix matrix = new Matrix();
        SVGParser.TextScanner scan = new SVGParser.TextScanner(val);
        scan.skipWhitespace();

        while(!scan.empty()) {
            String cmd = scan.nextFunction();
            if (cmd == null) {
                throw new SAXException("Bad transform function encountered in transform list: " + val);
            }

            Float ang;
            Float cx;
            Float cy;
            if (cmd.equals("matrix")) {
                scan.skipWhitespace();
                ang = scan.nextFloat();
                scan.skipCommaWhitespace();
                cx = scan.nextFloat();
                scan.skipCommaWhitespace();
                cy = scan.nextFloat();
                scan.skipCommaWhitespace();
                Float d = scan.nextFloat();
                scan.skipCommaWhitespace();
                Float e = scan.nextFloat();
                scan.skipCommaWhitespace();
                Float f = scan.nextFloat();
                scan.skipWhitespace();
                if (f == null || !scan.consume(')')) {
                    throw new SAXException("Invalid transform list: " + val);
                }

                Matrix m = new Matrix();
                m.setValues(new float[]{ang, cy, e, cx, d, f, 0.0F, 0.0F, 1.0F});
                matrix.preConcat(m);
            } else if (cmd.equals("translate")) {
                scan.skipWhitespace();
                ang = scan.nextFloat();
                cx = scan.possibleNextFloat();
                scan.skipWhitespace();
                if (ang == null || !scan.consume(')')) {
                    throw new SAXException("Invalid transform list: " + val);
                }

                if (cx == null) {
                    matrix.preTranslate(ang, 0.0F);
                } else {
                    matrix.preTranslate(ang, cx);
                }
            } else if (cmd.equals("scale")) {
                scan.skipWhitespace();
                ang = scan.nextFloat();
                cx = scan.possibleNextFloat();
                scan.skipWhitespace();
                if (ang == null || !scan.consume(')')) {
                    throw new SAXException("Invalid transform list: " + val);
                }

                if (cx == null) {
                    matrix.preScale(ang, ang);
                } else {
                    matrix.preScale(ang, cx);
                }
            } else if (cmd.equals("rotate")) {
                scan.skipWhitespace();
                ang = scan.nextFloat();
                cx = scan.possibleNextFloat();
                cy = scan.possibleNextFloat();
                scan.skipWhitespace();
                if (ang == null || !scan.consume(')')) {
                    throw new SAXException("Invalid transform list: " + val);
                }

                if (cx == null) {
                    matrix.preRotate(ang);
                } else {
                    if (cy == null) {
                        throw new SAXException("Invalid transform list: " + val);
                    }

                    matrix.preRotate(ang, cx, cy);
                }
            } else if (cmd.equals("skewX")) {
                scan.skipWhitespace();
                ang = scan.nextFloat();
                scan.skipWhitespace();
                if (ang == null || !scan.consume(')')) {
                    throw new SAXException("Invalid transform list: " + val);
                }

                matrix.preSkew((float)Math.tan(Math.toRadians((double)ang)), 0.0F);
            } else if (cmd.equals("skewY")) {
                scan.skipWhitespace();
                ang = scan.nextFloat();
                scan.skipWhitespace();
                if (ang == null || !scan.consume(')')) {
                    throw new SAXException("Invalid transform list: " + val);
                }

                matrix.preSkew(0.0F, (float)Math.tan(Math.toRadians((double)ang)));
            } else if (cmd != null) {
                throw new SAXException("Invalid transform list fn: " + cmd + ")");
            }

            if (scan.empty()) {
                break;
            }

            scan.skipCommaWhitespace();
        }

        return matrix;
    }

    protected static Length parseLength(String val) throws SAXException {
        if (val.length() == 0) {
            throw new SAXException("Invalid length value (empty string)");
        } else {
            int end = val.length();
            Unit unit = Unit.px;
            char lastChar = val.charAt(end - 1);
            if (lastChar == '%') {
                --end;
                unit = Unit.percent;
            } else if (end > 2 && Character.isLetter(lastChar) && Character.isLetter(val.charAt(end - 2))) {
                end -= 2;
                String unitStr = val.substring(end);

                try {
                    unit = Unit.valueOf(unitStr.toLowerCase(Locale.US));
                } catch (IllegalArgumentException var7) {
                    throw new SAXException("Invalid length unit specifier: " + val);
                }
            }

            try {
                float scalar = Float.parseFloat(val.substring(0, end));
                return new Length(scalar, unit);
            } catch (NumberFormatException var6) {
                throw new SAXException("Invalid length value: " + val, var6);
            }
        }
    }

    private static List<Length> parseLengthList(String val) throws SAXException {
        if (val.length() == 0) {
            throw new SAXException("Invalid length list (empty string)");
        } else {
            List<Length> coords = new ArrayList(1);
            SVGParser.TextScanner scan = new SVGParser.TextScanner(val);
            scan.skipWhitespace();

            while(!scan.empty()) {
                Float scalar = scan.nextFloat();
                if (scalar == null) {
                    throw new SAXException("Invalid length list value: " + scan.ahead());
                }

                Unit unit = scan.nextUnit();
                if (unit == null) {
                    unit = Unit.px;
                }

                coords.add(new Length(scalar, unit));
                scan.skipCommaWhitespace();
            }

            return coords;
        }
    }

    private static float parseFloat(String val) throws SAXException {
        if (val.length() == 0) {
            throw new SAXException("Invalid float value (empty string)");
        } else {
            try {
                return Float.parseFloat(val);
            } catch (NumberFormatException var2) {
                throw new SAXException("Invalid float value: " + val, var2);
            }
        }
    }

    private static float parseOpacity(String val) throws SAXException {
        float o = parseFloat(val);
        return o < 0.0F ? 0.0F : (o > 1.0F ? 1.0F : o);
    }

    private static Box parseViewBox(String val) throws SAXException {
        SVGParser.TextScanner scan = new SVGParser.TextScanner(val);
        scan.skipWhitespace();
        Float minX = scan.nextFloat();
        scan.skipCommaWhitespace();
        Float minY = scan.nextFloat();
        scan.skipCommaWhitespace();
        Float width = scan.nextFloat();
        scan.skipCommaWhitespace();
        Float height = scan.nextFloat();
        if (minX != null && minY != null && width != null && height != null) {
            if (width < 0.0F) {
                throw new SAXException("Invalid viewBox. width cannot be negative");
            } else if (height < 0.0F) {
                throw new SAXException("Invalid viewBox. height cannot be negative");
            } else {
                return new Box(minX, minY, width, height);
            }
        } else {
            throw new SAXException("Invalid viewBox definition - should have four numbers");
        }
    }

    private static void parsePreserveAspectRatio(SvgPreserveAspectRatioContainer obj, String val) throws SAXException {
        SVGParser.TextScanner scan = new SVGParser.TextScanner(val);
        scan.skipWhitespace();
        Alignment align = null;
        Scale scale = null;
        String word = scan.nextToken();
        if ("defer".equals(word)) {
            scan.skipWhitespace();
            word = scan.nextToken();
        }

        align = (Alignment)aspectRatioKeywords.get(word);
        scan.skipWhitespace();
        if (!scan.empty()) {
            String meetOrSlice = scan.nextToken();
            if (meetOrSlice.equals("meet")) {
                scale = Scale.Meet;
            } else {
                if (!meetOrSlice.equals("slice")) {
                    throw new SAXException("Invalid preserveAspectRatio definition: " + val);
                }

                scale = Scale.Slice;
            }
        }

        obj.preserveAspectRatio = new PreserveAspectRatio(align, scale);
    }

    private static SvgPaint parsePaintSpecifier(String val, String attrName) throws SAXException {
        if (val.startsWith("url(")) {
            int closeBracket = val.indexOf(")");
            if (closeBracket == -1) {
                throw new SAXException("Bad " + attrName + " attribute. Unterminated url() reference");
            } else {
                String href = val.substring(4, closeBracket).trim();
                SvgPaint fallback = null;
                val = val.substring(closeBracket + 1).trim();
                if (val.length() > 0) {
                    fallback = parseColourSpecifer(val);
                }

                return new PaintReference(href, fallback);
            }
        } else {
            return parseColourSpecifer(val);
        }
    }

    private static SvgPaint parseColourSpecifer(String val) throws SAXException {
        if (val.equals("none")) {
            return null;
        } else {
            return (SvgPaint)(val.equals("currentColor") ? CurrentColor.getInstance() : parseColour(val));
        }
    }

    private static Colour parseColour(String val) throws SAXException {
        int h1;
        int h2;
        int h3;
        if (val.charAt(0) == '#') {
            try {
                if (val.length() == 7) {
                    return new Colour(Integer.parseInt(val.substring(1), 16));
                } else if (val.length() == 4) {
                    int threehex = Integer.parseInt(val.substring(1), 16);
                    h1 = threehex & 3840;
                    h2 = threehex & 240;
                    h3 = threehex & 15;
                    return new Colour(h1 << 16 | h1 << 12 | h2 << 8 | h2 << 4 | h3 << 4 | h3);
                } else {
                    throw new SAXException("Bad hex colour value: " + val);
                }
            } catch (NumberFormatException var5) {
                throw new SAXException("Bad colour value: " + val);
            }
        } else if (val.toLowerCase(Locale.US).startsWith("rgb(")) {
            SVGParser.TextScanner scan = new SVGParser.TextScanner(val.substring(4));
            scan.skipWhitespace();
            h1 = parseColourComponent(scan);
            scan.skipCommaWhitespace();
            h2 = parseColourComponent(scan);
            scan.skipCommaWhitespace();
            h3 = parseColourComponent(scan);
            scan.skipWhitespace();
            if (!scan.consume(')')) {
                throw new SAXException("Bad rgb() colour value: " + val);
            } else {
                return new Colour(h1 << 16 | h2 << 8 | h3);
            }
        } else {
            return parseColourKeyword(val);
        }
    }

    private static int parseColourComponent(SVGParser.TextScanner scan) throws SAXException {
        float comp = scan.nextFloat();
        if (scan.consume('%')) {
            comp = comp * 256.0F / 100.0F;
        }

        return comp < 0.0F ? 0 : (comp > 255.0F ? 255 : (int)comp);
    }

    private static Colour parseColourKeyword(String name) throws SAXException {
        Integer col = (Integer)colourKeywords.get(name.toLowerCase(Locale.US));
        if (col == null) {
            throw new SAXException("Invalid colour keyword: " + name);
        } else {
            return new Colour(col);
        }
    }

    private static void parseFont(Style style, String val) throws SAXException {
        List<String> fontFamily = null;
        Length fontSize = null;
        Integer fontWeight = null;
        FontStyle fontStyle = null;
        String fontVariant = null;
        if ("|caption|icon|menu|message-box|small-caption|status-bar|".indexOf('|' + val + '|') == -1) {
            SVGParser.TextScanner scan = new SVGParser.TextScanner(val);
            String item = null;

            while(true) {
                item = scan.nextToken('/');
                scan.skipWhitespace();
                if (item == null) {
                    throw new SAXException("Invalid font style attribute: missing font size and family");
                }

                if (fontWeight != null && fontStyle != null) {
                    break;
                }

                if (!item.equals("normal")) {
                    if (fontWeight == null) {
                        fontWeight = (Integer)fontWeightKeywords.get(item);
                        if (fontWeight != null) {
                            continue;
                        }
                    }

                    if (fontStyle == null) {
                        fontStyle = (FontStyle)fontStyleKeywords.get(item);
                        if (fontStyle != null) {
                            continue;
                        }
                    }

                    if (fontVariant != null || !item.equals("small-caps")) {
                        break;
                    }

                    fontVariant = item;
                }
            }

            fontSize = parseFontSize(item);
            if (scan.consume('/')) {
                scan.skipWhitespace();
                item = scan.nextToken();
                if (item == null) {
                    throw new SAXException("Invalid font style attribute: missing line-height");
                }

                parseLength(item);
                scan.skipWhitespace();
            }

            fontFamily = parseFontFamily(scan.restOfText());
            style.fontFamily = fontFamily;
            style.fontSize = fontSize;
            style.fontWeight = fontWeight == null ? 400 : fontWeight;
            style.fontStyle = fontStyle == null ? FontStyle.Normal : fontStyle;
            style.specifiedFlags |= 122880L;
        }
    }

    private static List<String> parseFontFamily(String val) throws SAXException {
        List<String> fonts = null;
        SVGParser.TextScanner scan = new SVGParser.TextScanner(val);

        do {
            String item = scan.nextQuotedString();
            if (item == null) {
                item = scan.nextToken(',');
            }

            if (item == null) {
                break;
            }

            if (fonts == null) {
                fonts = new ArrayList();
            }

            fonts.add(item);
            scan.skipCommaWhitespace();
        } while(!scan.empty());

        return fonts;
    }

    private static Length parseFontSize(String val) throws SAXException {
        Length size = (Length)fontSizeKeywords.get(val);
        if (size == null) {
            size = parseLength(val);
        }

        return size;
    }

    private static Integer parseFontWeight(String val) throws SAXException {
        Integer wt = (Integer)fontWeightKeywords.get(val);
        if (wt == null) {
            throw new SAXException("Invalid font-weight property: " + val);
        } else {
            return wt;
        }
    }

    private static FontStyle parseFontStyle(String val) throws SAXException {
        FontStyle fs = (FontStyle)fontStyleKeywords.get(val);
        if (fs == null) {
            throw new SAXException("Invalid font-style property: " + val);
        } else {
            return fs;
        }
    }

    private static TextDecoration parseTextDecoration(String val) throws SAXException {
        if ("none".equals(val)) {
            return TextDecoration.None;
        } else if ("underline".equals(val)) {
            return TextDecoration.Underline;
        } else if ("overline".equals(val)) {
            return TextDecoration.Overline;
        } else if ("line-through".equals(val)) {
            return TextDecoration.LineThrough;
        } else if ("blink".equals(val)) {
            return TextDecoration.Blink;
        } else {
            throw new SAXException("Invalid text-decoration property: " + val);
        }
    }

    private static TextDirection parseTextDirection(String val) throws SAXException {
        if ("ltr".equals(val)) {
            return TextDirection.LTR;
        } else if ("rtl".equals(val)) {
            return TextDirection.RTL;
        } else {
            throw new SAXException("Invalid direction property: " + val);
        }
    }

    private static FillRule parseFillRule(String val) throws SAXException {
        if ("nonzero".equals(val)) {
            return FillRule.NonZero;
        } else if ("evenodd".equals(val)) {
            return FillRule.EvenOdd;
        } else {
            throw new SAXException("Invalid fill-rule property: " + val);
        }
    }

    private static LineCaps parseStrokeLineCap(String val) throws SAXException {
        if ("butt".equals(val)) {
            return LineCaps.Butt;
        } else if ("round".equals(val)) {
            return LineCaps.Round;
        } else if ("square".equals(val)) {
            return LineCaps.Square;
        } else {
            throw new SAXException("Invalid stroke-linecap property: " + val);
        }
    }

    private static LineJoin parseStrokeLineJoin(String val) throws SAXException {
        if ("miter".equals(val)) {
            return LineJoin.Miter;
        } else if ("round".equals(val)) {
            return LineJoin.Round;
        } else if ("bevel".equals(val)) {
            return LineJoin.Bevel;
        } else {
            throw new SAXException("Invalid stroke-linejoin property: " + val);
        }
    }

    private static Length[] parseStrokeDashArray(String val) throws SAXException {
        SVGParser.TextScanner scan = new SVGParser.TextScanner(val);
        scan.skipWhitespace();
        if (scan.empty()) {
            return null;
        } else {
            Length dash = scan.nextLength();
            if (dash == null) {
                return null;
            } else if (dash.isNegative()) {
                throw new SAXException("Invalid stroke-dasharray. Dash segemnts cannot be negative: " + val);
            } else {
                float sum = dash.floatValue();
                List<Length> dashes = new ArrayList();
                dashes.add(dash);

                while(!scan.empty()) {
                    scan.skipCommaWhitespace();
                    dash = scan.nextLength();
                    if (dash == null) {
                        throw new SAXException("Invalid stroke-dasharray. Non-Length content found: " + val);
                    }

                    if (dash.isNegative()) {
                        throw new SAXException("Invalid stroke-dasharray. Dash segemnts cannot be negative: " + val);
                    }

                    dashes.add(dash);
                    sum += dash.floatValue();
                }

                if (sum == 0.0F) {
                    return null;
                } else {
                    return (Length[])dashes.toArray(new Length[dashes.size()]);
                }
            }
        }
    }

    private static TextAnchor parseTextAnchor(String val) throws SAXException {
        if ("start".equals(val)) {
            return TextAnchor.Start;
        } else if ("middle".equals(val)) {
            return TextAnchor.Middle;
        } else if ("end".equals(val)) {
            return TextAnchor.End;
        } else {
            throw new SAXException("Invalid text-anchor property: " + val);
        }
    }

    private static Boolean parseOverflow(String val) throws SAXException {
        if (!"visible".equals(val) && !"auto".equals(val)) {
            if (!"hidden".equals(val) && !"scroll".equals(val)) {
                throw new SAXException("Invalid toverflow property: " + val);
            } else {
                return Boolean.FALSE;
            }
        } else {
            return Boolean.TRUE;
        }
    }

    private static CSSClipRect parseClip(String val) throws SAXException {
        if ("auto".equals(val)) {
            return null;
        } else if (!val.toLowerCase(Locale.US).startsWith("rect(")) {
            throw new SAXException("Invalid clip attribute shape. Only rect() is supported.");
        } else {
            SVGParser.TextScanner scan = new SVGParser.TextScanner(val.substring(5));
            scan.skipWhitespace();
            Length top = parseLengthOrAuto(scan);
            scan.skipCommaWhitespace();
            Length right = parseLengthOrAuto(scan);
            scan.skipCommaWhitespace();
            Length bottom = parseLengthOrAuto(scan);
            scan.skipCommaWhitespace();
            Length left = parseLengthOrAuto(scan);
            scan.skipWhitespace();
            if (!scan.consume(')')) {
                throw new SAXException("Bad rect() clip definition: " + val);
            } else {
                return new CSSClipRect(top, right, bottom, left);
            }
        }
    }

    private static Length parseLengthOrAuto(SVGParser.TextScanner scan) {
        return scan.consume("auto") ? new Length(0.0F) : scan.nextLength();
    }

    private static VectorEffect parseVectorEffect(String val) throws SAXException {
        if ("none".equals(val)) {
            return VectorEffect.None;
        } else if ("non-scaling-stroke".equals(val)) {
            return VectorEffect.NonScalingStroke;
        } else {
            throw new SAXException("Invalid vector-effect property: " + val);
        }
    }

    private static PathDefinition parsePath(String val) throws SAXException {
        SVGParser.TextScanner scan = new SVGParser.TextScanner(val);
        float currentX = 0.0F;
        float currentY = 0.0F;
        float lastMoveX = 0.0F;
        float lastMoveY = 0.0F;
        float lastControlX = 0.0F;
        float lastControlY = 0.0F;
        PathDefinition path = new PathDefinition();
        if (scan.empty()) {
            return path;
        } else {
            int pathCommand = scan.nextChar();
            if (pathCommand != 77 && pathCommand != 109) {
                return path;
            } else {
                while(true) {
                    scan.skipWhitespace();
                    Float x;
                    Float y;
                    Float x1;
                    Float y1;
                    Float x2;
                    Float y2;
                    switch(pathCommand) {
                        case 65:
                        case 97:
                            Float rx = scan.nextFloat();
                            Float ry = scan.checkedNextFloat(rx);
                            Float xAxisRotation = scan.checkedNextFloat(ry);
                            Boolean largeArcFlag = scan.checkedNextFlag(xAxisRotation);
                            Boolean sweepFlag = scan.checkedNextFlag(largeArcFlag);
                            x = scan.checkedNextFloat(sweepFlag);
                            y = scan.checkedNextFloat(x);
                            if (y != null && rx >= 0.0F && ry >= 0.0F) {
                                if (pathCommand == 97) {
                                    x = x + currentX;
                                    y = y + currentY;
                                }

                                path.arcTo(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y);
                                currentX = lastControlX = x;
                                currentY = lastControlY = y;
                                break;
                            }

                            Log.e("SVGParser", "Bad path coords for " + (char)pathCommand + " path segment");
                            return path;
                        case 67:
                        case 99:
                            x1 = scan.nextFloat();
                            y1 = scan.checkedNextFloat(x1);
                            x2 = scan.checkedNextFloat(y1);
                            y2 = scan.checkedNextFloat(x2);
                            x = scan.checkedNextFloat(y2);
                            y = scan.checkedNextFloat(x);
                            if (y == null) {
                                Log.e("SVGParser", "Bad path coords for " + (char)pathCommand + " path segment");
                                return path;
                            }

                            if (pathCommand == 99) {
                                x = x + currentX;
                                y = y + currentY;
                                x1 = x1 + currentX;
                                y1 = y1 + currentY;
                                x2 = x2 + currentX;
                                y2 = y2 + currentY;
                            }

                            path.cubicTo(x1, y1, x2, y2, x, y);
                            lastControlX = x2;
                            lastControlY = y2;
                            currentX = x;
                            currentY = y;
                            break;
                        case 72:
                        case 104:
                            x = scan.nextFloat();
                            if (x == null) {
                                Log.e("SVGParser", "Bad path coords for " + (char)pathCommand + " path segment");
                                return path;
                            }

                            if (pathCommand == 104) {
                                x = x + currentX;
                            }

                            path.lineTo(x, currentY);
                            currentX = lastControlX = x;
                            break;
                        case 76:
                        case 108:
                            x = scan.nextFloat();
                            y = scan.checkedNextFloat(x);
                            if (y == null) {
                                Log.e("SVGParser", "Bad path coords for " + (char)pathCommand + " path segment");
                                return path;
                            }

                            if (pathCommand == 108) {
                                x = x + currentX;
                                y = y + currentY;
                            }

                            path.lineTo(x, y);
                            currentX = lastControlX = x;
                            currentY = lastControlY = y;
                            break;
                        case 77:
                        case 109:
                            x = scan.nextFloat();
                            y = scan.checkedNextFloat(x);
                            if (y == null) {
                                Log.e("SVGParser", "Bad path coords for " + (char)pathCommand + " path segment");
                                return path;
                            }

                            if (pathCommand == 109 && !path.isEmpty()) {
                                x = x + currentX;
                                y = y + currentY;
                            }

                            path.moveTo(x, y);
                            currentX = lastMoveX = lastControlX = x;
                            currentY = lastMoveY = lastControlY = y;
                            pathCommand = pathCommand == 109 ? 108 : 76;
                            break;
                        case 81:
                        case 113:
                            x1 = scan.nextFloat();
                            y1 = scan.checkedNextFloat(x1);
                            x = scan.checkedNextFloat(y1);
                            y = scan.checkedNextFloat(x);
                            if (y == null) {
                                Log.e("SVGParser", "Bad path coords for " + (char)pathCommand + " path segment");
                                return path;
                            }

                            if (pathCommand == 113) {
                                x = x + currentX;
                                y = y + currentY;
                                x1 = x1 + currentX;
                                y1 = y1 + currentY;
                            }

                            path.quadTo(x1, y1, x, y);
                            lastControlX = x1;
                            lastControlY = y1;
                            currentX = x;
                            currentY = y;
                            break;
                        case 83:
                        case 115:
                            x1 = 2.0F * currentX - lastControlX;
                            y1 = 2.0F * currentY - lastControlY;
                            x2 = scan.nextFloat();
                            y2 = scan.checkedNextFloat(x2);
                            x = scan.checkedNextFloat(y2);
                            y = scan.checkedNextFloat(x);
                            if (y == null) {
                                Log.e("SVGParser", "Bad path coords for " + (char)pathCommand + " path segment");
                                return path;
                            }

                            if (pathCommand == 115) {
                                x = x + currentX;
                                y = y + currentY;
                                x2 = x2 + currentX;
                                y2 = y2 + currentY;
                            }

                            path.cubicTo(x1, y1, x2, y2, x, y);
                            lastControlX = x2;
                            lastControlY = y2;
                            currentX = x;
                            currentY = y;
                            break;
                        case 84:
                        case 116:
                            x1 = 2.0F * currentX - lastControlX;
                            y1 = 2.0F * currentY - lastControlY;
                            x = scan.nextFloat();
                            y = scan.checkedNextFloat(x);
                            if (y == null) {
                                Log.e("SVGParser", "Bad path coords for " + (char)pathCommand + " path segment");
                                return path;
                            }

                            if (pathCommand == 116) {
                                x = x + currentX;
                                y = y + currentY;
                            }

                            path.quadTo(x1, y1, x, y);
                            lastControlX = x1;
                            lastControlY = y1;
                            currentX = x;
                            currentY = y;
                            break;
                        case 86:
                        case 118:
                            y = scan.nextFloat();
                            if (y == null) {
                                Log.e("SVGParser", "Bad path coords for " + (char)pathCommand + " path segment");
                                return path;
                            }

                            if (pathCommand == 118) {
                                y = y + currentY;
                            }

                            path.lineTo(currentX, y);
                            currentY = lastControlY = y;
                            break;
                        case 90:
                        case 122:
                            path.close();
                            lastControlX = lastMoveX;
                            currentX = lastMoveX;
                            lastControlY = lastMoveY;
                            currentY = lastMoveY;
                            break;
                        default:
                            return path;
                    }

                    scan.skipCommaWhitespace();
                    if (scan.empty()) {
                        return path;
                    }

                    if (scan.hasLetter()) {
                        pathCommand = scan.nextChar();
                    }
                }
            }
        }
    }

    private static Set<String> parseRequiredFeatures(String val) throws SAXException {
        SVGParser.TextScanner scan = new SVGParser.TextScanner(val);

        HashSet result;
        for(result = new HashSet(); !scan.empty(); scan.skipWhitespace()) {
            String feature = scan.nextToken();
            if (feature.startsWith("http://www.w3.org/TR/SVG11/feature#")) {
                result.add(feature.substring("http://www.w3.org/TR/SVG11/feature#".length()));
            } else {
                result.add("UNSUPPORTED");
            }
        }

        return result;
    }

    private static Set<String> parseSystemLanguage(String val) throws SAXException {
        SVGParser.TextScanner scan = new SVGParser.TextScanner(val);
        HashSet result = new HashSet();

        while(!scan.empty()) {
            String language = scan.nextToken();
            int hyphenPos = language.indexOf(45);
            if (hyphenPos != -1) {
                language = language.substring(0, hyphenPos);
            }

            language = (new Locale(language, "", "")).getLanguage();
            result.add(language);
            scan.skipWhitespace();
        }

        return result;
    }

    private static Set<String> parseRequiredFormats(String val) throws SAXException {
        SVGParser.TextScanner scan = new SVGParser.TextScanner(val);
        HashSet result = new HashSet();

        while(!scan.empty()) {
            String mimetype = scan.nextToken();
            result.add(mimetype);
            scan.skipWhitespace();
        }

        return result;
    }

    private static String parseFunctionalIRI(String val, String attrName) throws SAXException {
        if (val.equals("none")) {
            return null;
        } else if (val.startsWith("url(") && val.endsWith(")")) {
            return val.substring(4, val.length() - 1).trim();
        } else {
            throw new SAXException("Bad " + attrName + " attribute. Expected \"none\" or \"url()\" format");
        }
    }

    private void style(Attributes attributes) throws SAXException {
        this.debug("<style>");
        if (this.currentElement == null) {
            throw new SAXException("Invalid document. Root element must be <svg>");
        } else {
            boolean isTextCSS = true;
            String media = "all";

            for(int i = 0; i < attributes.getLength(); ++i) {
                String val = attributes.getValue(i).trim();
                //SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()
                switch(SVGParser.SVGAttr.fromString(attributes.getLocalName(i)).ordinal()) {
                    case 39:
                        media = val;
                        break;
                    case 78:
                        isTextCSS = val.equals("text/css");
                }
            }

            if (isTextCSS && CSSParser.mediaMatches(media, MediaType.screen)) {
                this.inStyleElement = true;
            } else {
                this.ignoring = true;
                this.ignoreDepth = 1;
            }

        }
    }

    private void parseCSSStyleSheet(String sheet) throws SAXException {
        CSSParser cssp = new CSSParser(MediaType.screen);
        this.svgDocument.addCSSRules(cssp.parse(sheet));
    }

    private static enum SVGAttr {
        CLASS,
        clip,
        clip_path,
        clipPathUnits,
        clip_rule,
        color,
        cx,
        cy,
        direction,
        dx,
        dy,
        fx,
        fy,
        d,
        display,
        fill,
        fill_rule,
        fill_opacity,
        font,
        font_family,
        font_size,
        font_weight,
        font_style,
        gradientTransform,
        gradientUnits,
        height,
        href,
        id,
        marker,
        marker_start,
        marker_mid,
        marker_end,
        markerHeight,
        markerUnits,
        markerWidth,
        mask,
        maskContentUnits,
        maskUnits,
        media,
        offset,
        opacity,
        orient,
        overflow,
        pathLength,
        patternContentUnits,
        patternTransform,
        patternUnits,
        points,
        preserveAspectRatio,
        r,
        refX,
        refY,
        requiredFeatures,
        requiredExtensions,
        requiredFormats,
        requiredFonts,
        rx,
        ry,
        solid_color,
        solid_opacity,
        spreadMethod,
        startOffset,
        stop_color,
        stop_opacity,
        stroke,
        stroke_dasharray,
        stroke_dashoffset,
        stroke_linecap,
        stroke_linejoin,
        stroke_miterlimit,
        stroke_opacity,
        stroke_width,
        style,
        systemLanguage,
        text_anchor,
        text_decoration,
        transform,
        type,
        vector_effect,
        version,
        viewBox,
        width,
        x,
        y,
        x1,
        y1,
        x2,
        y2,
        viewport_fill,
        viewport_fill_opacity,
        visibility,
        UNSUPPORTED;

        private SVGAttr() {
        }

        public static SVGParser.SVGAttr fromString(String str) {
            if (str.equals("class")) {
                return CLASS;
            } else if (str.indexOf(95) != -1) {
                return UNSUPPORTED;
            } else {
                try {
                    return valueOf(str.replace('-', '_'));
                } catch (IllegalArgumentException var2) {
                    return UNSUPPORTED;
                }
            }
        }
    }

    protected static class TextScanner {
        protected String input;
        protected int position = 0;

        public TextScanner(String input) {
            this.input = input.trim();
        }

        public boolean empty() {
            return this.position == this.input.length();
        }

        protected boolean isWhitespace(int c) {
            return c == 32 || c == 10 || c == 13 || c == 9;
        }

        public void skipWhitespace() {
            while(this.position < this.input.length() && this.isWhitespace(this.input.charAt(this.position))) {
                ++this.position;
            }

        }

        protected boolean isEOL(int c) {
            return c == 10 || c == 13;
        }

        public boolean skipCommaWhitespace() {
            this.skipWhitespace();
            if (this.position == this.input.length()) {
                return false;
            } else if (this.input.charAt(this.position) != ',') {
                return false;
            } else {
                ++this.position;
                this.skipWhitespace();
                return true;
            }
        }

        public Float nextFloat() {
            int floatEnd = this.scanForFloat();
            if (floatEnd == this.position) {
                return null;
            } else {
                Float result = Float.parseFloat(this.input.substring(this.position, floatEnd));
                this.position = floatEnd;
                return result;
            }
        }

        public Float possibleNextFloat() {
            int start = this.position;
            this.skipCommaWhitespace();
            Float result = this.nextFloat();
            if (result != null) {
                return result;
            } else {
                this.position = start;
                return null;
            }
        }

        public Float checkedNextFloat(Object lastRead) {
            if (lastRead == null) {
                return null;
            } else {
                this.skipCommaWhitespace();
                return this.nextFloat();
            }
        }

        public Integer nextInteger() {
            int intEnd = this.scanForInteger();
            if (intEnd == this.position) {
                return null;
            } else {
                Integer result = Integer.parseInt(this.input.substring(this.position, intEnd));
                this.position = intEnd;
                return result;
            }
        }

        public Integer nextChar() {
            return this.position == this.input.length() ? null : Integer.valueOf(this.input.charAt(this.position++));
        }

        public Length nextLength() {
            Float scalar = this.nextFloat();
            if (scalar == null) {
                return null;
            } else {
                Unit unit = this.nextUnit();
                return unit == null ? new Length(scalar, Unit.px) : new Length(scalar, unit);
            }
        }

        public Boolean nextFlag() {
            if (this.position == this.input.length()) {
                return null;
            } else {
                char ch = this.input.charAt(this.position);
                if (ch != '0' && ch != '1') {
                    return null;
                } else {
                    ++this.position;
                    return ch == '1';
                }
            }
        }

        public Boolean checkedNextFlag(Object lastRead) {
            if (lastRead == null) {
                return null;
            } else {
                this.skipCommaWhitespace();
                return this.nextFlag();
            }
        }

        public boolean consume(char ch) {
            boolean found = this.position < this.input.length() && this.input.charAt(this.position) == ch;
            if (found) {
                ++this.position;
            }

            return found;
        }

        public boolean consume(String str) {
            int len = str.length();
            boolean found = this.position <= this.input.length() - len && this.input.substring(this.position, this.position + len).equals(str);
            if (found) {
                this.position += len;
            }

            return found;
        }

        protected int advanceChar() {
            if (this.position == this.input.length()) {
                return -1;
            } else {
                ++this.position;
                return this.position < this.input.length() ? this.input.charAt(this.position) : -1;
            }
        }

        public String nextToken() {
            return this.nextToken(' ');
        }

        public String nextToken(char terminator) {
            if (this.empty()) {
                return null;
            } else {
                int ch = this.input.charAt(this.position);
                if (!this.isWhitespace(ch) && ch != terminator) {
                    int start = this.position;

                    for(ch = this.advanceChar(); ch != -1 && ch != terminator && !this.isWhitespace(ch); ch = this.advanceChar()) {
                    }

                    return this.input.substring(start, this.position);
                } else {
                    return null;
                }
            }
        }

        public String nextFunction() {
            if (this.empty()) {
                return null;
            } else {
                int start = this.position;

                int ch;
                for(ch = this.input.charAt(this.position); ch >= 97 && ch <= 122 || ch >= 65 && ch <= 90; ch = this.advanceChar()) {
                }

                int end;
                for(end = this.position; this.isWhitespace(ch); ch = this.advanceChar()) {
                }

                if (ch == 40) {
                    ++this.position;
                    return this.input.substring(start, end);
                } else {
                    this.position = start;
                    return null;
                }
            }
        }

        private int scanForFloat() {
            if (this.empty()) {
                return this.position;
            } else {
                int lastValidPos = this.position;
                int start = this.position;
                int ch = this.input.charAt(this.position);
                if (ch == 45 || ch == 43) {
                    ch = this.advanceChar();
                }

                if (Character.isDigit(ch)) {
                    lastValidPos = this.position + 1;

                    for(ch = this.advanceChar(); Character.isDigit(ch); ch = this.advanceChar()) {
                        lastValidPos = this.position + 1;
                    }
                }

                if (ch == 46) {
                    lastValidPos = this.position + 1;

                    for(ch = this.advanceChar(); Character.isDigit(ch); ch = this.advanceChar()) {
                        lastValidPos = this.position + 1;
                    }
                }

                if (ch == 101 || ch == 69) {
                    ch = this.advanceChar();
                    if (ch == 45 || ch == 43) {
                        ch = this.advanceChar();
                    }

                    if (Character.isDigit(ch)) {
                        lastValidPos = this.position + 1;

                        for(ch = this.advanceChar(); Character.isDigit(ch); ch = this.advanceChar()) {
                            lastValidPos = this.position + 1;
                        }
                    }
                }

                this.position = start;
                return lastValidPos;
            }
        }

        private int scanForInteger() {
            if (this.empty()) {
                return this.position;
            } else {
                int lastValidPos = this.position;
                int start = this.position;
                int ch = this.input.charAt(this.position);
                if (ch == 45 || ch == 43) {
                    ch = this.advanceChar();
                }

                if (Character.isDigit(ch)) {
                    lastValidPos = this.position + 1;

                    for(ch = this.advanceChar(); Character.isDigit(ch); ch = this.advanceChar()) {
                        lastValidPos = this.position + 1;
                    }
                }

                this.position = start;
                return lastValidPos;
            }
        }

        public String ahead() {
            int start;
            for(start = this.position; !this.empty() && !this.isWhitespace(this.input.charAt(this.position)); ++this.position) {
            }

            String str = this.input.substring(start, this.position);
            this.position = start;
            return str;
        }

        public Unit nextUnit() {
            if (this.empty()) {
                return null;
            } else {
                int ch = this.input.charAt(this.position);
                if (ch == '%') {
                    ++this.position;
                    return Unit.percent;
                } else if (this.position > this.input.length() - 2) {
                    return null;
                } else {
                    try {
                        Unit result = Unit.valueOf(this.input.substring(this.position, this.position + 2).toLowerCase(Locale.US));
                        this.position += 2;
                        return result;
                    } catch (IllegalArgumentException var3) {
                        return null;
                    }
                }
            }
        }

        public boolean hasLetter() {
            if (this.position == this.input.length()) {
                return false;
            } else {
                char ch = this.input.charAt(this.position);
                return ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z';
            }
        }

        public String nextQuotedString() {
            if (this.empty()) {
                return null;
            } else {
                int start = this.position;
                int ch = this.input.charAt(this.position);
                int endQuote = ch;
                if (ch != '\'' && ch != '"') {
                    return null;
                } else {
                    for(ch = this.advanceChar(); ch != -1 && ch != endQuote; ch = this.advanceChar()) {
                    }

                    if (ch == -1) {
                        this.position = start;
                        return null;
                    } else {
                        ++this.position;
                        return this.input.substring(start + 1, this.position - 1);
                    }
                }
            }
        }

        public String restOfText() {
            if (this.empty()) {
                return null;
            } else {
                int start = this.position;
                this.position = this.input.length();
                return this.input.substring(start);
            }
        }
    }
}
